package com.practice.security.aes;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class AESCipher {

	private static final String AES_ALGORITHM = "AES";

	private static final String AES_CIPHER_NAME = "AES/CBC/PKCS5Padding";

	public static void main(String[] args) throws IOException, NoSuchAlgorithmException {

		SecretKeySpec secretKeySpec = new SecretKeySpec(AESKeyGenerator.readSecretKey(), AES_ALGORITHM);

		IvParameterSpec ivParameterSpec = new IvParameterSpec(AESKeyGenerator.readInitVector());

		String plainText = "7xb37songa5asi1bcxg";

		String cipherText = encryptText(plainText, secretKeySpec, ivParameterSpec);

		System.out.println(cipherText);

		System.out.println(decryptText(cipherText, secretKeySpec, ivParameterSpec));
	}

	public static String encryptText(String plainText, SecretKeySpec secretKeySpec, IvParameterSpec ivParameterSpec) {

		byte[] plainTextBytes = plainText.getBytes();
		byte[] cipherTextBytes = encrypt(plainTextBytes, secretKeySpec, ivParameterSpec);
		String cipherText = Base64.getEncoder().encodeToString(cipherTextBytes);
		return cipherText;
	}

	private static byte[] encrypt(byte[] plainTextBytes, SecretKeySpec secretKeySpec, IvParameterSpec ivParameterSpec) {

		byte[] cipherTextBytes = null;
		try {
			Cipher cipher = Cipher.getInstance(AES_CIPHER_NAME);
			cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
			cipherTextBytes = cipher.doFinal(plainTextBytes);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException
				| InvalidKeyException | InvalidAlgorithmParameterException
				| IllegalBlockSizeException | BadPaddingException e) {
			e.printStackTrace();
		}
		return cipherTextBytes;
	}

	public static String decryptText(String cipherText, SecretKeySpec secretKeySpec, IvParameterSpec ivParameterSpec) {

		byte[] cipherTextBytes = Base64.getDecoder().decode(cipherText);
		byte[] plainTextBytes = decrypt(cipherTextBytes, secretKeySpec, ivParameterSpec);
		String plainText = new String(plainTextBytes);
		return plainText;
	}

	private static byte[] decrypt(byte[] cipherTextBytes, SecretKeySpec secretKeySpec, IvParameterSpec ivParameterSpec) {

		byte[] plainTextBytes = null;
		try {
			Cipher cipher = Cipher.getInstance(AES_CIPHER_NAME);
			cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
			plainTextBytes = cipher.doFinal(cipherTextBytes);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException
				| InvalidKeyException | InvalidAlgorithmParameterException
				| IllegalBlockSizeException | BadPaddingException e) {
			e.printStackTrace();
		}
		return plainTextBytes;
	}

}
